package org.example.common;

import io.grpc.*;
import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder;
import org.example.sec06.BankService;
import org.example.sec06.TransferService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Arrays;
import java.util.function.Consumer;
/**
 * @author Administrator
 */
public class GrpcServer {
    private static final Logger LOG = LoggerFactory.getLogger(GrpcServer.class);
    private static final int PORT = 5555;
    private final Server server;

    private GrpcServer(Server server) {
        this.server = server;
    }

    public static GrpcServer create(BindableService... bindableServices) {
        return create(PORT, bindableServices);
    }

    public static GrpcServer create(int port, BindableService... bindableService) {
        return create(port, serverBuilder -> {
            Arrays.asList(bindableService).forEach(serverBuilder::addService);
        });
//        var builder = ServerBuilder.forPort(port)
//                .keepAliveTime(10, TimeUnit.SECONDS)
//                .keepAliveTimeout(1, TimeUnit.SECONDS)
//                .maxConnectionIdle(25, TimeUnit.SECONDS);
//        Arrays.asList(bindableService).forEach(builder::addService);
    }

    public static GrpcServer create(int port, Consumer<ServerBuilder<?>> consumer) {
        var builder = ServerBuilder.forPort(port);
        consumer.accept(builder);
        return new GrpcServer(builder.build());
    }
    public static GrpcServer create2(int port, Consumer<NettyServerBuilder> consumer) {
        var builder = NettyServerBuilder.forPort(port);
        consumer.accept(builder);
        return new GrpcServer(builder.build());
    }
    public GrpcServer start() {
        var services = server.getServices()
                .stream().map(ServerServiceDefinition::getServiceDescriptor)
                .map(ServiceDescriptor::getName).toList();
        try {
            server.start();
            LOG.info("server started. listening on port {}. services : {}", server.getPort(), services);
            return this;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void await() {
        try {
            server.awaitTermination();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public void stop() {
        server.shutdown();
        LOG.info("server stop....");
    }

    public static void main(String[] args) throws Exception {
        GrpcServer.create(new BankService(), new TransferService())
                .start().await();
    }
}
